Tópicos Especiais em Estatística Comp.

Desempenho de Funções em R e WebScraping com R

Prof. Jodavid Ferreira

UFPE




Desempenhos de funções em R









Teste de Algoritmos



  • A criação de funções é primordial para desenvolvimentos de novas funcionalidades, implementações de novas propostas, e em nosso caso, a implementação de uma teoria desenvolvida em nossas pesquisas.
  • Apenas aprender a criar funções, pode não ser o suficiente para garantir que o código seja executado de forma rápida e eficiente, com excessão de que essa criação seja realizada já pensando nessas etapas.
  • Então, testar funções em R é uma tarefa importante, pois é possível verificar onde e quais códigos, funções, algoritmos são mais eficientes que outros.

Teste de Algoritmos


# Pré-requisitos
# devtools::install_github("hadley/lineprof")

library(lineprof)


f <- function() {
  pause(0.1)
}


# Encontrar "bottlenecks" - gargalhos
#options(browser = 'chromium');
l <- lineprof(f())

shine(l)

Teste de Algoritmos


Vamos comparar duas funções da para calcular média?

  1. Implementação do próprio R.
  2. Implementação manual
#Gerando um amostra
x<-rnorm(1*10^7)


# Criando uma função para soma
soma <- function(x)
{
  saida <- 0
  for(i in 1:length(x))
  {
    saida <- saida+x[i]
  }
  
  return(saida)
}

Teste de Algoritmos



# Criando uma função para média
media <- function(x)
{
  saida <- soma(x)/length(x)
  return(saida)
}


# Verificar se as duas funções retornam o mesmo resultado
all.equal(mean(x),media(x))
[1] TRUE
# Função caso não seja igual retornar uma informação
stopifnot(all.equal(mean(x),media(x)))


# Verificando a função média
verif_funcao <- lineprof(media(x))

shine(verif_funcao)

Teste de Algoritmos



# Comparar qual funcao é mais "fast"
# install.packages("microbenchmark")
library(microbenchmark)


res <- microbenchmark(
  mean(x),
  media(x),
    times = 10L

)

Teste de Algoritmos


#Resultado
res
Unit: milliseconds
     expr       min        lq      mean    median        uq       max neval
  mean(x)  20.05238  20.09639  20.24549  20.25113  20.35316  20.50893    10
 media(x) 192.18133 192.87069 193.71672 193.13452 193.31633 200.03675    10
#Grafico do tempo com GGPlot2
if (require("ggplot2")) {
  autoplot(res)
}

Teste de Algoritmos


#Visualizando por BoxPlot
boxplot(res[1,])

Teste de Algoritmos - Exemplo 2


# -------------------------------------------------------------------------- #
# Função de verossimilhança para uma distribuição normal
log_likelihood <- function(params, data) {
  mu <- params[1]
  sigma <- params[2]
  
  # Log-verossimilhança negativa
  nll <- -sum(dnorm(data, mean = mu, sd = sigma, log = TRUE))
  return(nll)
}

# Função para estimação de parâmetros
estimate_params_r <- function(data) {
  init_params <- c(mean(data), sd(data))
  result <- optim(par = init_params, fn = log_likelihood, data = data)
  return(result$par)
}
# -------------------------------------------------------------------------- #

Teste de Algoritmos - Exemplo 2


#include <Rcpp.h>
using namespace Rcpp;

// Função de verossimilhança negativa em C++
// [[Rcpp::export]]
double log_likelihood_cpp(NumericVector params, NumericVector data) {
  double mu = params[0];
  double sigma = params[1];
  int n = data.size();
  double nll = 0.0;  // Log-verossimilhança negativa
  
  for(int i = 0; i < n; i++) {
    double term = (data[i] - mu) * (data[i] - mu) / (2 * sigma * sigma);
    nll += term + log(sigma) + 0.5 * log(2 * M_PI);
  }
  
  return nll;
}

// Função para estimação de parâmetros em C++
// [[Rcpp::export]]
NumericVector estimate_params_cpp(NumericVector data) {
  NumericVector init_params = NumericVector::create(mean(data), sd(data));
  Function optim("optim");
  
  // Usando a função optim do R para otimização, passando a função C++ como callback
  List result = optim(_["par"] = init_params, _["fn"] = Rcpp::InternalFunction(log_likelihood_cpp), _["data"] = data);
  return result["par"];
}
# -------------------------------------------------------------------------- #
# Script R para integrar com o C++
library(Rcpp)
sourceCpp("log_likelihood.cpp")
# -------------------------------------------------------------------------- #

Teste de Algoritmos - Exemplo 2


# -------------------------------------------------------------------------- #
# Implementação manual da densidade da normal
log_likelihood_manual <- function(params, data) {
  mu <- params[1]
  sigma <- params[2]
  
  # Log-verossimilhança negativa manualmente calculada
  n <- length(data)
  nll <- -sum(-log(sqrt(2 * pi * sigma^2)) - ((data - mu)^2) / (2 * sigma^2))
  return(nll)
}

# Função para estimação de parâmetros
estimate_params_manual <- function(data) {
  init_params <- c(mean(data), sd(data))
  result <- optim(par = init_params, fn = log_likelihood_manual, data = data)
  return(result$par)
}
# -------------------------------------------------------------------------- #

Teste de Algoritmos - Exemplo 2


library(microbenchmark)

# Exemplo de uso
set.seed(42)
data <- rnorm(10000, mean = 5, sd = 2)

benchmark_result <- microbenchmark(
  R = estimate_params_r(data),
  Cpp = estimate_params_cpp(data),
  Manual = estimate_params_manual(data),
  times = 100L
)

print(benchmark_result)
Unit: milliseconds
   expr      min       lq     mean   median       uq       max neval
      R 5.643004 8.719610 8.855638 8.907514 9.103202 21.174926   100
    Cpp 1.593910 3.408051 3.269749 3.473949 3.541126  5.641858   100
 Manual 2.131362 3.743267 3.979577 3.790411 3.845735  9.730337   100

Teste de Algoritmos - Exemplo 2


#Grafico do tempo com GGPlot2
if (require("ggplot2")) {
  autoplot(benchmark_result)
}








WebScraping com R


O que é Web Scraping?



  • O Web Scraping é uma área da Text Mining (Mineração de Texto) ;



O que é Mineração de Texto?

Segundo o Livro ‘Text Mining in Practice with R’:


* “Mineração de texto é o processo de destilar1 insights de texto”.

Onde a mineração de texto se encaixa?



* Para acadêmicos, pode auxiliar na compreensão de transcrições qualitativas ou em um estudo da linguagem;


* Para empresas, pode render informações interessantes que auxiliarão na modelagem preditiva por exemplo;


* Aos profissionais de marketing, podem auxiliar na criação de textos, fornecendo recomendações precisas para sua organização.


* Então, a mineração de texto pode ser usada em qualquer decisão baseada em dados, onde o texto se encaixa naturalmente como uma entrada.

Pacote rvest



rvest ajuda você a extrair (ou colher) dados de páginas da web.

Ele foi projetado para funcionar com magrittr (pacote responsável pelo operador pipe %>%) para facilitar a expressão de tarefas comuns de web scraping e inspiradas em bibliotecas como a beautiful soup e RoboBrowser.

Atualmente o R possui seu próprio pipe, é utilizado com o símbolo |>.

O que é HTML e CSS ?


  • HTML (HyperText Markup Language - Linguagem de Marcação de Hipertexto) - é uma linguagem de marcação usada para estruturar uma página web.

  • CSS (Cascading Style Sheets - Folha de Estilo em Cascata) - é usado para estilizar os elementos escritos no HTML.


O que precisamos saber ?

Em HTML e CSS, existe a possibilidade de aplicar estilos através de ‘class’ e ‘id’;

  • HTML :
    • class : é o atributo global formado por uma lista das classes de um elemento, separada por espaços.

    • id : define um identificador exclusivo (ID) que deve ser único por todo o documento.

  • CSS: usado para personalizar a parte visual dos sites.

Instalando o rvest



Instalando o rvest através do devtools


install.packages("devtools")
library(devtools)
devtools::install_github("tidyverse/rvest")



Lendo o pacote:


library(rvest)

Exemplo 1:

Extraindo informações do site Trading Economics


Passo 1: Lendo a URL

Usando a função read_html do pacote xml2 (este pacote é uma dependência do rvest) para ler a url.

library(rvest)

url <- "https://tradingeconomics.com/country-list/balance-of-trade"
trading_webpage <- read_html(url)


Link: https://tradingeconomics.com/country-list/balance-of-trade

Exemplo 1:

Extraindo informações do site Trading Economics


Essas informações do site Trading Economics representam dados econômicos de diferentes países:

  1. Country (País): Refere-se ao país ao qual os dados econômicos se aplicam. Pode ser o nome completo do país ou uma abreviação.

  2. Last (Último): Este campo mostra o valor mais recente do indicador econômico específico. Esse valor representa a última medição disponível desse dado.

  3. Previous (Anterior): Este campo apresenta o valor anterior do mesmo indicador econômico, ou seja, o valor que foi registrado na medição anterior.

  4. Reference (Referência): Indica o período ao qual os dados se referem. Por exemplo, pode ser o mês ou o trimestre em que os dados foram coletados.

  5. Unit (Unidade): Especifica a unidade de medida dos dados. Pode ser uma moeda (por exemplo, USD, EUR), uma porcentagem, uma taxa de crescimento, entre outras formas de medição.

Exemplo 1:

Extraindo informações do site Trading Economics


Passo 2:

Duas funções serão utilizadas aqui:

  1. html_nodes: Use esta função para extrair os nós que desejamos (neste caso nós com “.field-congressperson_name” como classe css)
  2. html_table: Use esta função para extrair tabelas de um site.
#Scraping  usando classe css ‘table’
trading_names_html <- html_nodes(trading_webpage, '.table')
trading_names <- html_table(trading_names_html)
head(trading_names[[1]],3)
# A tibble: 3 × 5
  Country       Last Previous Reference Unit       
  <chr>        <dbl>    <dbl> <chr>     <chr>      
1 Afghanistan  -6798    -5169 Dec/23    USD Million
2 Albania     -52150   -41945 Jul/24    ALL Million
3 Algeria       3790     2338 Sep/23    USD Million

Exemplo 2:

Texto de um WebSite


library(ggplot2)

trading_df <- trading_names[[1]]

ggplot(trading_df, aes(x=Last)) +
  geom_histogram() +
  labs(title="", x ="Valor mais recente do indicador econômico",
       y = "Frequência") +
  theme_minimal()
print("Summary da coluna Last")
[1] "Summary da coluna Last"
summary(trading_df$Last)
      Min.    1st Qu.     Median       Mean    3rd Qu.       Max. 
-5.205e+09 -3.570e+03 -2.620e+02 -2.896e+07  9.950e+02  4.793e+06 

Exemplo 2:

Texto de um WebSite


library(ggplot2)

trading_df <- trading_names[[1]][1:5,]

ggplot(trading_df, aes(y=Country,fill=Reference)) +
  geom_col(aes(x=Last)) +
  labs(title="", x ="Valor mais recente do indicador econômico",
       y = "País",fill="Período: ") +
  scale_fill_brewer()+
  theme_minimal() +
  theme(legend.position = "bottom")

Exemplo 2:

Texto de um WebSite


Neste segundo exemplo vamos obter o texto de um site e analisá-lo.

Exemplo 2:

Texto de Site


Link: https://brasil.elpais.com/brasil/2021-01-26/todos-os-brasileiros-estao-com-seus-dados-a-venda-e-ha-muito-pouco-o-que-se-pode-fazer-para-se-proteger.html


Passo 1: Lendo a URL

library(rvest)

url <- "https://brasil.elpais.com/brasil/2021-01-26/todos-os-brasileiros-estao-com-seus-dados-a-venda-e-ha-muito-pouco-o-que-se-pode-fazer-para-se-proteger.html"
webpage <- read_html(url)

Passo 2: Extraindo texto de Site

# Passo 2:
#Scraping  usando ‘p’
names_html <-html_nodes(webpage, 'p')
names <- html_text(names_html)
head(names)
[1] "Um megavazamento de dados pessoais de 223 milhões de brasileiros tornado público na semana passada pela empresa de segurança digital PSafe pode ser o maior na história do país e tem tudo para ser a primeira prova de fogo da Autoridade Nacional de Proteção de Dados (ANPD), criada a partir da entrada em vigor da Lei Geral de Proteção de Dados (LGPD) em agosto do ano passado. Também é o primeiro incidente desta magnitude que se tem notícia no Brasil. A lista com milhões de nomes completos, CPFs e datas de nascimento —de pessoas vivas e mortas— estava disponível para download gratuito a partir de um fórum de discussão na deep web —cópias do arquivo original foram feitas e podiam ser encontradas por qualquer um a partir de buscadores de internet. Em troca de bitcoins, o perfil anônimo responsável pelo vazamento dizia ser possível obter ainda retratos, endereço, telefone, declaração do Imposto de Renda, listas de familiares, renda mensal, score de crédito e muito mais dos alvos em questão. Na terça-feira, após a repercussão do caso, o material foi retirado do ar no fórum de livre acesso com qualquer navegador, mas continua em negociação na deep web."
[2] "Na lista há dados de gente famosa e autoridades públicas. De acordo com a PSafe, cibercriminosos também tiveram acesso a informações detalhadas sobre mais de 104 milhões de veículos e dados sigilosos de 40 milhões de empresas."                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
[3] "“O vazamento é real, confirmada a autenticidade de todos os dados, é o maior vazamento da história do Brasil e certamente um dos maiores do mundo”, afirma Marco DeMello, CEO da PSafe. “Estávamos monitorando a deep web para alguns de nossos clientes e nos deparamos com milhões de CPNJs em negociação, rastreamos e chegamos na fonte”, diz. Ele afirma que a equipe de segurança da empresa entrou em contato com o hacker, que disse cobrar 100 dólares por pacotes com os registros de mil pessoas, empresas ou veículos. Ele diz não ser brasileiro e que vai vender no máximo 1 milhão de contatos para cada comprador, pois pretende ganhar dinheiro com essa base de dados por muito tempo ainda. Segundo DeMello, nas conversas o hacker diz que roubou a base dados da Serasa/Experian, empresa de análise de crédito que cria perfis dos consumidores brasileiros entre outras atividades, mas não tem como saber se isso é verdade. A mesma alegação aparece na página onde ele vende o material, assim como no nome de alguns arquivos."                                                                                                                                                
[4] "Apoie a produção de notícias como esta. Assine o EL PAÍS por 30 dias por 1 US$"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
[5] "Procurada pela reportagem através de sua assessoria de imprensa, a Serasa/Experian respondeu, após a publicação, que a empresa não é a fonte dos dados vazados. “Embora o hacker afirme que parte dos dados veio da Serasa, com base em nossa análise detalhada até este ponto, concluímos que a Serasa não é a fonte”, diz a nota enviada. “Também não vemos evidências de que nossos sistemas tenham sido comprometidos”, afirma a empresa, que ainda diz não possuir todos os dados oferecidos na internet e que está em contato com autoridades reguladoras para ajudar no caso. "                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
[6] "Os dados estavam disponíveis no fórum de discussões desde o começo do mês e foram identificados pela empresa de segurança na terça-feira da semana passada, e teriam sido extraídos da fonte original por 18 meses entre 2018 e 2020. Segundo o CEO da PSafe, algumas informações foram checadas por amostragem e são reais. “É assustador, porque com isso qualquer golpista que comprar os dados pode fazer coisas inimagináveis em nome de outras como comprar e vender veículos e imóveis, contrair dívidas, invadir contas bancárias e outros sistemas informatizados que usam essas imagens, abrir empresas, o estrago possível é muito grande”, diz DeMello."                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

Exemplo 2:

Texto de Site


Passo 3: Preparação dos dados

Organizando os dados para geração do gráfico da Nuvem de Tags

  • Corpus: função que transforma vetores/listas em coleções de documentos que contêm texto.
# Início do código para Nuvem de palavras
library(tm)

# -------
# Colocando as palavras em minusculos
# -------
texto <- tolower(names)
# -------
# Removendo as stopwords
texto <- removeWords(texto, stopwords(kind = "portuguese"))
# -------

Passo 3:

Preparação dos dados - cont.


# Transformando em formato Corpus
texto <- Corpus(VectorSource(texto),
                readerControl = list(reader = reader(VectorSource(texto)),
                                     language = "pt"))
# -------
# Removendo as stopwords de arquivo.txt
# -------
file <- url("https://jodavid.github.io/Slide-Introdu-o-a-Web-Scrapping-com-rvest/stopwords_pt_BR.txt")
stopwords_ptBR <- read.table(file)
stopwords_ptBR <- unlist(stopwords_ptBR, use.names = FALSE)
texto <- tm_map(texto, removeWords, stopwords_ptBR)

# -------
# Descobrindo tamanho da lista
n <- length(texto)
# -------
# Removendo pontuacao
for(i in 1:n)
  {
    # Remover pontuacao, preservando abreviacoes
    texto[[i]] <- removePunctuation(texto[[i]],
                                    preserve_intra_word_contractions = TRUE,
                                    preserve_intra_word_dashes = TRUE)
    # Removendo quotations
    texto[[i]] <- stringr::str_replace_all(texto[[i]], setNames(c('','','',''), c('“ ', '“',' ”','”')))
  }
# -------

Passo 4:

Geração de um gráfico de Nuvem de Tags


library(wordcloud)
pal <- brewer.pal(6,"Dark2")
pal <- pal[-(1)]


wordcloud(words = texto, min.freq = 2, random.order = TRUE,
          colors = pal,
          use.r.layout = TRUE, rot.per = 0.5)

Passo 4:

Geração de um gráfico de Nuvem de Tags


Referências para serem utilizadas



Extras:

  • https://www.conventionalcommits.org/
  • https://seesparkbox.com/foundry/semantic_commit_messages
  • http://karma-runner.github.io/1.0/dev/git-commit-msg.html




OBRIGADO!


Slide produzido com quarto